#pragma once
#include <core/time/time.h>
#include <uam/ServerTimeMgr.h>

#include <map>
#include <mutex>
#include <vector>

#include "BondContainer.h"
#include "CompanyReport.h"
#include "SSBankQuote.h"
#include "SSCFETSQuote.h"
#include "SSXCQuote.h"
#include "bondlib.h"
// ***************************************************************
//  SSCompanyReportManager   version:  1.0
//  -------------------------------------------------------------
//  author:	Tony.luo
//    date: 2016-08-23
//   brief: 公司报价 broker报价，后续调整只有报价才分配内存
//  -------------------------------------------------------------
//  Copyright (C) 2016 - Sumscope All Rights Reserved
// ***************************************************************
//
// ***************************************************************

// #ifdef DEL(p)
// 	#undef DEL(p)
// #endif

#define DEL(p)     \
  if (p != NULL) { \
    delete p;      \
    p = NULL;      \
  }

#if defined(WIN32) || defined(_WINDOWS)
#include <windows.h>

#define localtime_r(ti, tm) localtime_s(tm, ti)
#define gmtime_r(ti, tm) gmtime_s(tm, ti)

#else
#include <sys/time.h>
#endif

class StatDumper;
class S_BONDLIB_EXPORT CReportManagerBase {
 public:
  typedef qb::base::HighResTime HighResTime;
  enum kActionType {
    kActionTypeAdd,
    kActionTypeClear,
    kActionTypeClearReport,
    kActionTypeReserve,
    kActionTypeGetReport,
    kActionTypeGetReportOrAdd,
    kActionTypeSetReport,
    kActionTypeCount
  };
  class ScopedDumper {
    StatDumper* m_dumper;
    HighResTime m_timer;
    int m_length;
    kActionType m_type;

   public:
    ScopedDumper(StatDumper* dumper, kActionType type, int length);
    ~ScopedDumper();
  };

 protected:
  // typedef qboost::Spinlock LockType;
  // typedef qboost::ScopedSpinLock ScopedLockType;
  typedef std::recursive_mutex LockType;
  typedef std::lock_guard<std::recursive_mutex> ScopedLockType;

  StatDumper* m_dumper;
  LockType m_mutex;  // 互斥信号
 public:
  // 之所以将之前的CSPMutex在这里替换,是考虑性能
  using Scoped = ScopedLockType;
  CReportManagerBase();
  ~CReportManagerBase();
  virtual int GetSize() const;
  virtual int GetMemory(int mode);

  /*
  by scofined.qi
  此宏是统计CSSReportManager对象的各个接口使用情况以及内存情况,注释和开启后均不影响代码执行,默认关闭
  对象在宏开启后,每间隔m_log_gap毫秒后输出一次日志,默认是4000ms
  部分接口已经加锁增加了安全性
  */
#define SCOPED_REPORT_DUMPER( \
    TYPE)  // ScopedDumper _scoped(m_dumper, TYPE, m_vctRep.size());
 public:   // 调试用
  void SetName(const char* name);
  void SetItemSize(int itemSize);
  void DumpStatus(int mode = 0) const;
};
template <class T>
class S_BONDLIB_EXPORT CSSReportManager : public CReportManagerBase {
 public:
  CSSReportManager() : CReportManagerBase() {
    T t;
    SetName(t.GetName());
    SetItemSize(t.GetItemSize());
  }
  ~CSSReportManager() { Clear(); }

 public:
  bool Add(T* pReport) {
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeAdd);
    m_vctRep.push_back(pReport);
    return true;
  }

  void Clear() {
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeClear);
    for (size_t i = 0; i < m_vctRep.size(); ++i) {
      DEL(m_vctRep[i]);
    }
    m_vctRep.clear();
  }

  void ClearReport() {
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeClearReport);
    for (size_t i = 0; i < m_vctRep.size(); ++i) {
      if (m_vctRep[i] != NULL) {
        m_vctRep[i]->Clear();
      }
    }
  }

  void Reserve(int nCapacity) {
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeReserve);
    m_vctRep.reserve(nCapacity);
  }

  virtual int GetSize() const override {
    int size = 0;
    ScopedLockType lock(const_cast<LockType&>(m_mutex));
    for (size_t i = 0; i < m_vctRep.size(); ++i) {
      if (m_vctRep[i]) size++;
    }
    return size;
  }
  virtual int GetMemory(int mode) override {
    int mem = 0;
    ScopedLockType lock(m_mutex);
    for (size_t i = 0; i < m_vctRep.size(); ++i) {
      if (m_vctRep[i]) mem += m_vctRep[i]->GetBytes(mode);
    }
    mem += m_vctRep.capacity() * sizeof(T*);
    return mem;
  }

  T* GetReport(int nIndex) {
    // if (AfxGetUserAccountManager().IsBrokerMobileOnline())return NULL;
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeGetReport);
    if (nIndex < 0 || nIndex >= (int)m_vctRep.size()) return nullptr;
    return m_vctRep[nIndex];
  }

  //-------------------------------------------------------------------------
  // Summary:
  // 		得到报价对象，若不存在，则会自动创建出来.更新报价数据时使用
  // Parameters:
  // 		nIndex -  下标
  // Returns:
  // 		报价对象
  //-------------------------------------------------------------------------
  T* GetReportOrAdd(int nIndex) {
    if (nIndex < 0) {
      return NULL;
    }
    int nBondSize = CBondContainer::instance().GetSize();
    if (nIndex >= nBondSize) {
      return NULL;
    }

    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeGetReportOrAdd);
    // 债券容器增加数据时，需要扩展数据
    if (nIndex >= (int)m_vctRep.size()) {
      m_vctRep.resize(nBondSize);
    }

    if (m_vctRep[nIndex] == NULL) {
      m_vctRep[nIndex] = new T();
    }
    return m_vctRep[nIndex];
  }

  //-------------------------------------------------------------------------
  // Summary:
  // 		设置报价对象，
  // Parameters:
  // 		nIndex -  下标
  // 		T* - 报价对象 必须是new的对象，clear会释放内存
  // Returns:
  // 		设置成功返回true
  //-------------------------------------------------------------------------
  bool SetReport(int nIndex, T* pObj) {
    ScopedLockType lock(m_mutex);
    SCOPED_REPORT_DUMPER(kActionTypeSetReport);
    if (nIndex < 0 || nIndex >= (int)m_vctRep.size()) {
      return false;
    }

    DEL(m_vctRep[nIndex]);
    m_vctRep[nIndex] = pObj;
  }

  LockType& GetMutex() { return m_mutex; }

 private:
  std::vector<T*> m_vctRep;  // 报价
};

template <class T>
class S_BONDLIB_EXPORT CSSCFETSReportManager : public CSSReportManager<T> {
 public:
  CSSCFETSReportManager() : CSSReportManager<T>() {
    m_mapver[0] = 0;
    m_mapver[1] = 0;
    m_mapver[2] = 0;
    m_lastupdate = 0;
  }
  ~CSSCFETSReportManager(){};

  void ClearVersion() {
    for (std::map<int, int>::iterator it = m_mapver.begin();
         it != m_mapver.end(); it++) {
      it->second = 0;
    }
    m_lastupdate = 0;
  }

  void UpdateVersion(int type, int ver, time_t updatetime) {
    auto it = m_mapver.find(type);
    if (it == m_mapver.end())
      m_mapver.insert(make_pair(type, ver));
    else
      it->second = max(it->second, ver);
    m_lastupdate = max(m_lastupdate, updatetime);
  }

  int GetVersion(int type) { return m_mapver[type]; }

  bool isDayChanged() {
    struct tm tmLast = {0};
    struct tm tmNow = {0};
    time_t t = ServerTimeMgr::instance().serverTime();
    localtime_r(&m_lastupdate, &tmLast);
    localtime_r(&t, &tmNow);
    if (tmLast.tm_mday != tmNow.tm_mday || tmLast.tm_mon != tmNow.tm_mon ||
        tmLast.tm_year != tmNow.tm_year)
      return true;
    return false;
  }

 private:
  std::map<int, int> m_mapver;
  time_t m_lastupdate;  // 最后更新时间
};

template <class T>
class S_BONDLIB_EXPORT CSSCFETSDealQuoteManager : public CSSReportManager<T> {
 public:
  CSSCFETSDealQuoteManager() : CSSReportManager<T>() {
    m_ver = 0;
    m_lastupdate = 0;
  }
  ~CSSCFETSDealQuoteManager(){};

  void ClearVersion() {
    m_ver = 0;
    m_lastupdate = 0;
  }
  void UpdateVersion(int ver, time_t updatetime) {
    m_ver = max(m_ver, ver);
    m_lastupdate = max(m_lastupdate, updatetime);
  }

  int GetVersion() { return m_ver; }

  bool isDayChanged() {
    struct tm tmLast = {0};
    struct tm tmNow = {0};
    time_t t = ServerTimeMgr::instance().serverTime();
    localtime_r(&m_lastupdate, &tmLast);
    localtime_r(&t, &tmNow);
    if (tmLast.tm_mday != tmNow.tm_mday || tmLast.tm_mon != tmNow.tm_mon ||
        tmLast.tm_year != tmNow.tm_year)
      return true;
    return false;
  }

 private:
  int m_ver;
  time_t m_lastupdate;  // 最后更新时间
};

class CBondCompanyRep;
class CBondBankRep;
class CXCQuoteRep;
class CCFETSQuoteRep;
class CCFETSDealQuoteRep;

#define BrokerRepMng GetBrokerReportManager()  // m_vctrep;	//Broker公司报价
#define BrokerBPRepMng \
  GetBrokerMixedBPReportManager()  // m_vctbkclt;	//QB BankClient报价
#define BankClientRepMng \
  GetBankClientReportManager()             // m_vctbkclt;	//QB BankClient报价
#define BankRepMng GetBankReportManager()  // Bank 报价
#define XCQuoteRepMng GetXCQuoteReportManager()  // 国债券期货：交易所报价
#define CfetsRepMng GetCfetsReportManager()         // cfets报价
#define CfetsDealRepMng GetCfetsDealQuoteManager()  // cfets成交行情

S_BONDLIB_EXPORT CSSReportManager<CBondCompanyRep>* GetBrokerReportManager();
S_BONDLIB_EXPORT CSSReportManager<CBondCompanyRep>*
GetBrokerMixedBPReportManager();
S_BONDLIB_EXPORT CSSReportManager<CBondBankRep>* GetBankClientReportManager();
S_BONDLIB_EXPORT CSSReportManager<CBondBankRep>* GetBankReportManager();
S_BONDLIB_EXPORT CSSReportManager<CXCQuoteRep>* GetXCQuoteReportManager();
S_BONDLIB_EXPORT CSSCFETSReportManager<CCFETSQuoteRep>* GetCfetsReportManager();
S_BONDLIB_EXPORT CSSCFETSDealQuoteManager<CCFETSDealQuoteRep>*
GetCfetsDealQuoteManager();
